package myJs.tool

import myJs.myPkg.jquery.{$, JQuery}
import org.scalajs.dom.{Blob, BlobPropertyBag, window}

import scala.scalajs.js.{Date, ThisFunction1}
import myJs.Implicits._
import myJs.api.Api
import myJs.myPkg.{FileSaver, LayerOptions, Typeahead, layer}
import org.scalajs.dom.window.localStorage
import scalatags.Text.all._

import scala.concurrent.Future
import scala.scalajs.js
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import shared.tsPojo.Tool.Png2jpeg
import shared.tsPojo.TsPojo
import slinky.web.html.s

import scala.collection.immutable.SeqMap
import scala.scalajs.js.typedarray.Uint8Array
import scala.scalajs.js.JSConverters._
import typings.csstype.csstypeStrings

/**
 * Created by yz on 24/4/2022
 */
object Tool {

  val pattern = "yyyy-mm-dd"

  val zhInfo = "Info"
  val layerOptions = LayerOptions(title = zhInfo, closeBtn = 0, skin = "layui-layer-molv", btn = List())


  val zhRunning = "Running..."
  val myElement = div(id := "content")(
    span(id := "info")(zhRunning),
    " ",
    img(src := s"${Api.images}/running2.gif", width := 30, height := 20, cls := "runningImage")
  ).render

  val confirmButtonClass = "btn-danger"
  val cancelButtonClass = "green"

  def element(info: String) = {
    div(id := "content",
      span(id := "info", info,
        span(id := "progress", "")), " ",
      img(src := s"${Api.images}/running2.gif", width := 30, height := 20, cls := "runningImage")
    ).render
  }

  val loadingElement = element("Running...")

  def timeBefore = (dateStr: String, dbDateStr: String) => {
    val date = new Date(dateStr)
    val dbDate = new Date(dbDateStr)
    dbDate.setUTCHours(0, 0, 0, 0)
    date.getTime() <= dbDate.getTime()
  }

  def timeAfter = (dateStr: String, dbDateStr: String) => {
    val date = new Date(dateStr)
    val dbDate = new Date(dbDateStr)
    dbDate.setUTCHours(0, 0, 0, 0)
    date.getTime() >= dbDate.getTime()
  }

  def b2Display(b: Boolean) = {
    if (b) csstypeStrings.block else csstypeStrings.none
  }

  def selectLeft: Unit = {
    val idInfo = window.location.href.replaceAll(".*/#/", "").
      replaceAll("\\?.*$", "")
    selectLeft(idInfo)
  }

  def selectLeft(idInfo: String): Unit = {
    val tmpIdInfos = idInfo.split("/").toList
    val idInfos = tmpIdInfos.size match {
      case 2 | 3 => tmpIdInfos.drop(1)
      case _ => tmpIdInfos
    }
    val mainId = idInfos.head
    val liId = idInfos.getOrElse(1, "")
    val menuContainer = $(".page-sidebar ul")
    menuContainer.children("li.active").removeClass("active")
    menuContainer.children("li").children("ul").hide()
    $(s"#${mainId} ul>li").removeClass("open")
    $(s"#${mainId}").addClass("active")
    if (liId.nonEmpty) {
      $(s"#${mainId} ul").show()
      $(s"#${mainId} #${liId}").addClass("open")
    }
  }

  def getAccount = {
    localStorage.getItem("account")
  }

  def useLoadingF(showLoading: Boolean = true)(f: () => Future[Any]) = {
    val index = if (showLoading) {
      val options = Tool.layerOptions.copy(shade = List("0.1", "#fff"))
      layer.load(0, options)
    } else 0
    f().map { x =>
      if (showLoading) {
        layer.close(index)
      }
    }
  }

  def findInputByName(name: String) = {
    $(s":input[name='${name}']")
  }

  def checkedMap2Search(name: String, checkedMap: SeqMap[String, Boolean]) = {
    val values = checkedMap.filter(_._2).map(_._1)
    if (values.isEmpty) {
      ujson.Obj()
    } else {
      ujson.Obj(
        "name" -> name,
        "kind" -> "checkbox",
        "value" -> values,
      )
    }
  }

  def highlighterF: ThisFunction1[Typeahead, String, String] = (y: Typeahead, item: String) => {
    val input = y.query
    val query = extractor(input).replaceAll("[\\-\\[\\]{}()*+?.,\\\\^$|#\\s]", "\\$&")
    val r = s"(?i)${query}".r
    r.replaceAllIn(item, matcher =>
      s"<strong>${matcher.group(0)}</strong>"
    )
  }

  def extractor(query: String) = {
    val result = js.RegExp("([^,]+)$").exec(query)
    if (result != null && result(1).isDefined) {
      result(1).toString.trim
    } else ""
  }

  val singleUpdater: js.ThisFunction1[Typeahead, String, String] = (y: Typeahead, item: String) => {
    s"${y.$element.`val`().toString.replaceAll("[^,]*$", "")}${item}"
  }

  val matcher: js.ThisFunction1[Typeahead, String, AnyVal] = (y: Typeahead, item: String) => {
    val tquery = extractor(y.query)
    ~(item.toLowerCase.indexOf(tquery.toLowerCase))
  }

  def downloadCsv(fileName: String, content: js.Any) = {
    val blob = new Blob(js.Array(content), new BlobPropertyBag {
      `type` = "text/csv;charset=utf-8"
    })
    FileSaver.saveAs(blob, fileName)
  }

  def downloadTxt(fileName: String, content: js.Any) = {
    val blob = new Blob(js.Array(content), new BlobPropertyBag {
      `type` = "text/plain;charset=utf-8"
    })
    FileSaver.saveAs(blob, fileName)
  }

  def base642binaryArray(content: String) = {
    val byteCharacters = window.atob(content)
    val sliceSize = 512
    val byteArrays = byteCharacters.grouped(sliceSize).map { slice =>
      val byteNumbers = slice.map(_.toShort).toJSArray
      new Uint8Array(byteNumbers)
    }
    byteArrays.toJSArray.map(_.asInstanceOf[js.Any])
  }

  def downloadPng(imgSrc: String, fileName: String) = {
    val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
    val base64 = imgSrc.replaceAll("^data:image/png;base64,", "")
    val byteArrays = Tool.base642binaryArray(base64)
    val blob = new Blob(byteArrays, new BlobPropertyBag {
      `type` = "image/png"
    })
    FileSaver.saveAs(blob, fileName)
    layer.close(index)
  }

  def downloadJpeg(imgSrc: String, fileName: String) = {
    import TsPojo.tool._
    val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
    val base64 = imgSrc.replaceAll("^data:image/png;base64,", "")
    val request = Png2jpeg.Request(base64 = base64)
    Api.tool.png2jpeg(request).map { response =>
      val byteArrays = Tool.base642binaryArray(response.base64)
      val blob = new Blob(byteArrays, new BlobPropertyBag {
        `type` = "image/jpeg"
      })
      FileSaver.saveAs(blob, fileName)
      layer.close(index)
    }
    ()
  }

  def downloadPdf(imgSrc: String, fileName: String) = {
    import TsPojo.tool._
    val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
    val base64 = imgSrc.replaceAll("^data:image/png;base64,", "")
    val request = Png2jpeg.Request(base64 = base64)
    Api.tool.png2pdf(request).map { response =>
      val byteArrays = Tool.base642binaryArray(response.base64)
      val blob = new Blob(byteArrays, new BlobPropertyBag {
        `type` = "application/pdf"
      })
      FileSaver.saveAs(blob, fileName)
      layer.close(index)
    }
    ()
  }

  def downloadSvg(imgSrc: String, fileName: String) = {
    import TsPojo.tool._
    val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
    val base64 = imgSrc.replaceAll("^data:image/png;base64,", "")
    val request = Png2jpeg.Request(base64 = base64)
    Api.tool.png2svg(request).map { response =>
      val byteArrays = Tool.base642binaryArray(response.base64)
      val blob = new Blob(byteArrays, new BlobPropertyBag {
        `type` = "image/svg+xml;charset=utf-8"
      })
      FileSaver.saveAs(blob, fileName)
      layer.close(index)
    }
    ()
  }

  def dbFmt(v: String) = {
    if (v.isDouble) {
      ujson.Num(v.toDouble)
    } else {
      ujson.Str(v)
    }
  }


}
